﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using GameSchool.Models.Interfaces;
using GameSchool.Models;
using GameSchool.Models.ViewModels;

namespace GameSchool.Models.Repositories
{

    public class PointsRepository
    {
        GameSchoolDBDataContext db = new GameSchoolDBDataContext();
        LevelRepository lrep = new LevelRepository();

        public void AddToScoreTable(Score s)
        {
            db.Scores.InsertOnSubmit(s);
        }

        //Fetches everything from the Score table 
        public IQueryable<Score> GetTotalPoints()
        {
            return db.Scores;              
        }

        //Fetches totalpoints for a certain User 
        public Score GetTotalPointsByID(int? uID)
        {
            var item = (from s in db.Scores
                       where s.ID == uID
                       select s).SingleOrDefault();
            return item;
        }

        //Fetches total points for a single user in a single course
        public int? GetCoursePoints(int? cID , Guid uID)
        {

            var result = (from p in db.AssignmentScores
                          from s in db.Assignments
                          from e in db.Levels
                          where p.AssignmentID == s.ID //Find the assignment in AssignmentScores
                          where e.ID == s.LevelID //Make sure we have the correct level selected
                          where e.CourseID == cID //And the correct course selected
                          where p.UserID == uID //Find the right data for the user
                          select p.Points).Sum(); //Select the sum of all the assignment scores

            return result;

        }

        //Fetches points for a single assignment from a single user
        public AssignmentScore GetAssignmentPoints(int? aID, Guid uID)
        {
            var result = (from p in db.AssignmentScores
                          where p.AssignmentID == aID
                          where p.UserID == uID
                          select p).SingleOrDefault();

            return result;
        }

        //Fetches points in a certain level for a single user
        public int? GetLevelPoints(int? lID, Guid uID)
        {
            int? result = (from p in db.AssignmentScores
                          from s in db.Assignments
                          where s.LevelID == lID
                          where p.UserID == uID
                          where p.AssignmentID == s.ID
                          select p.Points).Sum();

            return result;
        }
        
            public List<PointsViewModel> GetHighScoresAndPositionFromAssignment(Guid guid, int aID)
            {
                
                using (GameSchoolDBDataContext  db = new GameSchoolDBDataContext())
                {
                    var query = from s in db.AssignmentScores
                                from p in db.UserProfiles
                                where s.AssignmentID == aID
                                where p.UserID == guid
                                orderby s.Points descending
                                select new
                                {
                                    Userid = s.UserID,
                                    PlayerName = p.Name,
                                    PlayerScore = s.Points
                                };

                    return query.AsEnumerable() // Client-side from here on
                                .Select((player, index) => new PointsViewModel()
                                        {
                                                                                      
                                            userID = player.Userid,
                                            name = player.PlayerName,
                                            myPoints = player.PlayerScore,
                                           
                                            position  = index + 1
                                        }).ToList();
                                

         }                       

                }
            public List<PointsViewModel> GetHighScoresAndPositionFromCourse(Guid guid, IOrderedEnumerable<PointsViewModel> list)
            {

                
                {
                    var query = from s in list
                                
                                select new
                                {
                                    Userid = s.userID,
                                    PlayerName = s.name,
                                    PlayerScore = s.myPoints
                                };

                    return query.AsEnumerable() // Client-side from here on
                                .Select((player, index) => new PointsViewModel()
                                {

                                    userID = player.Userid,
                                    name = player.PlayerName,
                                    myPoints = player.PlayerScore,

                                    position = index + 1
                                }).ToList();


                }

            }
            

            public int? GetMaxLevelPoints(int? lID, Guid uID)
            {
                int? quizpoints = null, handinpoints = null, lecturepoints = null;
            
                var ass = lrep.GetAssignmentsByLevel(lID);

                if (ass.Count() > 0)
                {
                    try{

                        var ass2 = lrep.GetQuizsByLevel(lID);


                        //Fetch all quizpoints 
                        if (ass2.Count() > 0)
                        {
                            quizpoints = (from p in db.Quizs
                                      from s in db.Assignments
                                      where s.LevelID == lID
                                      where p.ID == s.ResourceID
                                      select p.MaxPoints).Sum(); //Sum them up
                        }
                        else
                        {
                            quizpoints = 0;
                        }
                }

                //If it throws an error throw that mofo out the do'
                catch(ArgumentNullException)
                {
                    quizpoints = 0;
                }

                try{

                    var ass3 = lrep.GetHandInsByLevel(lID);

                    //Fetch all HandIn points
                    if (ass3.Count() > 0)
                    {
                        handinpoints = (from p in db.HandIns
                                   from s in db.Assignments
                                   where s.LevelID == lID
                                   where p.ID == s.ResourceID
                                   select p.MaxPoints).Sum(); //Sum them up
                    }
                    else
                    {
                        handinpoints = 0;
                    }

                //If it throws an error throw that mofo out the do'
                }
                catch(ArgumentNullException)
                {
                    handinpoints = 0;
                }

                try
                {
                    var ass4 = lrep.GetLecturesByLevel(lID);

                    //Fetch all lecture points
                    if (ass4.Count() > 0)
                    {
                        lecturepoints = (from p in db.Lectures
                                   from s in db.Assignments
                                   where s.LevelID == lID
                                   where p.ID == s.ResourceID
                                   select p.MaxPoints).Sum(); //Sum them up
                    }
                    else
                    {
                        lecturepoints = 0;
                    }
                }

                //If it throws an error throw that mofo out the do'
                catch (ArgumentNullException)
                {
                    lecturepoints = 0;
                }
                
                //SUM ALL THE SUMS!
                return quizpoints + handinpoints + lecturepoints;
            }

            return 0;
        }

        public void AddPoints(AssignmentScore item)
        {
            db.AssignmentScores.InsertOnSubmit(item);
        }

        //Edit the scores for an assignment, doesn't work though
        public void editScore(AssignmentScore item)
        {
             AssignmentScore oldItem = db.AssignmentScores.Where(x => x.ID == item.ID).SingleOrDefault();
             if (oldItem != null)
             {
                oldItem.Points = item.Points;
                oldItem.Bonuspoints = item.Bonuspoints;
             }   

        }

        public void Save()
        {
            db.SubmitChanges();
        }

        //Removes a single user from a course
        public void RemoveUserFromCourse(int? cID,Guid uID)
        {
            IsInCourse cor = (from p in db.IsInCourses
                              where p.CourseID == cID
                              where p.UserID == uID
                              select p).SingleOrDefault();

            db.IsInCourses.DeleteOnSubmit(cor);

        }

        //Fetches the total points for a single course
        public IOrderedEnumerable<PointsViewModel> GetTotalPointsForCourse(int? cID)
        {
            UserRepository urep = new UserRepository();
            PointsRepository prep = new PointsRepository();

            Guid guid = new Guid();
            //Fetch the current user's ID
            guid = (Guid)Membership.GetUser().ProviderUserKey;

            //Make a list of PointViewModels to load everything into later
            List<PointsViewModel> list = new List<PointsViewModel>();

            var usersincourse = urep.GetUsersByCourse(cID);

            foreach( var user in usersincourse )
            {
                PointsViewModel points = new PointsViewModel();
                Guid id = new Guid();
                id = user.UserID;
                points.myPoints = GetCoursePoints(cID, id);
                points.userID = id;
                list.Add(points);


            }

            var newlist = list.OrderByDescending(x => x.myPoints);
            return newlist;
        }
        //Fetches the total points for a single Level in a single Course
        public IOrderedEnumerable<PointsViewModel> GetTotalPointsForLevel(int? cID,int? lID)
        {
            UserRepository urep = new UserRepository();
            PointsRepository prep = new PointsRepository();

            Guid guid = new Guid();
            //Fetch the current user's ID
            guid = (Guid)Membership.GetUser().ProviderUserKey;

            //Make a list of PointViewModels to load everything into later
            List<PointsViewModel> list = new List<PointsViewModel>();

            var usersincourse = urep.GetUsersByCourse(cID);

            foreach (var user in usersincourse)
            {
                PointsViewModel points = new PointsViewModel();
                Guid id = new Guid();
                id = user.UserID;
                points.myPoints = GetLevelPoints(lID, id);
                points.userID = id;
                list.Add(points);


            }

            var newlist = list.OrderByDescending(x => x.myPoints);
            return newlist;
        }
          

        
    }
}